﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace WFL.Data
{
    public class EntityDefinition
    {
        public static EntityDefinition Create(Type type, string provider,EntityDefinitionManager manager)
        {
            EntityDefinition item = new EntityDefinition();
            item.Type = type;
            item._manager = manager;

            List<CombineInfo> combineList = new List<CombineInfo>();
            object[] attributes = type.GetCustomAttributes(typeof(DefinitionAttribute), true);
            if (attributes != null & attributes.Length > 0)
            {
                foreach (object attribute in attributes)
                {
                    TableAttribute lastTableAttribute = null;
                    if (attribute is TableAttribute)
                    {
                        TableAttribute tableAttribute = (TableAttribute)attribute;
                        item.Table = new TableInfo();
                        if (string.IsNullOrEmpty(tableAttribute.Provider))
                        {
                            if (lastTableAttribute == null
                                || string.IsNullOrEmpty(lastTableAttribute.Provider))
                            {
                                lastTableAttribute = tableAttribute;
                                item.Table.Name = tableAttribute.Name;
                                item.Table.Alias = tableAttribute.Alias;
                            }
                        }
                        else if (tableAttribute.Provider.Equals(provider, StringComparison.InvariantCulture))
                        {
                            lastTableAttribute = tableAttribute;
                            item.Table.Name = tableAttribute.Name;
                            item.Table.Alias = tableAttribute.Alias;
                        }
                    }
                    else if (attribute is CombineAttribute)
                    {
                        CombineAttribute tempAttribute = (CombineAttribute)attribute;
                        combineList.Add(new CombineInfo(tempAttribute.Type));
                    }
                    else
                    {
                        throw new NotSupportedException(string.Format("未支持的特性\"{0}\"", attribute.GetType().FullName));
                    }
                }
            }
            if (combineList.Count > 0)
            {
                //调整类型顺序，使其符合外键关联顺序
                //主键类型在外键类型前面
                //目前暂时支持两种关联
                //1、主外键关联
                //2、两个类型的外键指向同一个主键（由此产生的外键链暂时不予支持，这种情况下两个类型的权重不用调整）
                for (int i = 0; i < combineList.Count; i++)
                {
                    for (int j = i + 1; j < combineList.Count; j++)
                    {
                        int relation = TestReferenceRelation(combineList[i].Type, combineList[j].Type, manager);
                        
                    }
                }
                //根据类型顺序值，调整类型列表顺序
                combineList.Sort(delegate (CombineInfo x, CombineInfo y)
                {
                    if (x.Order == y.Order)
                    {
                        return 0;
                    }
                    return x.Order < y.Order ? -1 : 1;
                });
                item.Combines = combineList.ToArray();

                throw new NotImplementedException();
            }
            if (item.Table == null)
            {
                if (item.Combines == null)
                {
                    item.Table = new TableInfo();
                    item.Table.Name = type.Name;
                }
            }
            else
            {
                if (string.IsNullOrEmpty(item.Table.Name))
                {
                    item.Table.Name = type.Name;
                }
            }
            PropertyInfo[] propertyInfos = type.GetProperties(BindingFlags.Public
                | BindingFlags.Instance
                | BindingFlags.GetProperty
                | BindingFlags.SetProperty);
            List<PropertyDefinition> list = new List<PropertyDefinition>();
            List<PropertyDefinition> foreignKeys = new List<PropertyDefinition>();
            foreach (PropertyInfo propertyInfo in propertyInfos)
            {
                PropertyDefinition property = PropertyDefinition.Create(propertyInfo, provider);
                if (property != null)
                {
                    list.Add(property);
                    if (property.PrimaryKey != null
                        && item.PrimaryKeyProperty == null)
                    {
                        item.PrimaryKeyProperty = property;
                    }
                    if (property.ForeignKey != null)
                    {
                        foreignKeys.Add(property);
                    }
                }
            }
            item.Properties = list.ToArray();
            if (foreignKeys.Count > 0)
            {
                item.ForeignKeyProperties = foreignKeys.ToArray();
            }
            return item;
        }

        /// <summary>
        /// 测试类型1和类型2的外键引用关系
        /// </summary>
        /// <param name="type1">类型1</param>
        /// <param name="type2">类型2</param>
        /// <param name="manager">类型定义管理器</param>
        /// <returns>类型1引用类型2，返回1；类型2引用类型1，返回-1；没有引用关系或者引用到同一个其他类型返回0</returns>
        private static int TestReferenceRelation(Type type1, Type type2, EntityDefinitionManager manager)
        {
            EntityDefinition entity1 = manager.Get(type1);
            EntityDefinition entity2 = manager.Get(type2);
            //bool sure = false;
            //if (entity1.ForeignKeyProperties != null)
            //{
            //    //判断是否有1到2的外键
            //    foreach (PropertyDefinition foreignKeyProperty in entity1.ForeignKeyProperties)
            //    {
            //        if (foreignKeyProperty.ForeignKey.ReferenceType == entity2.Type)
            //        {
            //            sure = true;
            //            if (combineList[i].Order <= combineList[j].Order)
            //            {
            //                //类型i对应的序号将要提升的偏移量
            //                int offset = combineList[j].Order + 1 - combineList[i].Order;
            //                //把原有序号中大于等于类型i的类型的序号都提升相应的偏移量（包括类型i自身）
            //                foreach (CombineInfo combine in combineList)
            //                {
            //                    if (combine.Order >= combineList[i].Order)
            //                    {
            //                        combine.Order += offset;
            //                    }
            //                }
            //            }
            //            break;
            //        }
            //    }
            //}

            throw new NotImplementedException();
        }


        private EntityDefinitionManager _manager;

        public Type Type 
        { 
            get; 
            set; 
        }

        public CombineInfo[] Combines
        {
            get;
            set;
        }

        public TableInfo Table
        {
            get;
            set;
        }

        public PropertyDefinition[] Properties 
        { 
            get; 
            set; 
        }

        public PropertyDefinition PrimaryKeyProperty
        {
            get;
            set;
        }

        public PropertyDefinition[] ForeignKeyProperties
        {
            get;
            set;
        }

        public PropertyDefinition GetProperty(string name)
        {
            foreach (PropertyDefinition property in Properties)
            {
                if (property.PropertyInfo.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
                {
                    return property;
                }
            }
            throw new Exception(string.Format("在实体{0}上找不到属性{1}", Type.Name, name));
        }
    }
}
